package controllers;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.Date;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import models.SystemOperator;
import models.SystemOperator;

import com.alibaba.fastjson.JSON;
import com.sun.org.apache.bcel.internal.generic.IUSHR;

import play.Play;
import play.cache.Cache;
import play.libs.Codec;
import play.libs.Images;
import play.mvc.Before;
import play.mvc.Catch;
import play.mvc.Controller;
import services.AuthorityService;
import services.OperatorService;
import utils.BizConstants;
import utils.HtmlToDoc;
import vos.HtmlReqException;
import vos.JSONReqException;
import vos.Result;
import vos.ResultVo;
import vos.ReturnCode;

/**
 * 过滤器、登录
 * 
 * @ClassName: BaseController 
 * @author: wangsm
 * @date: 2016年4月14日 下午4:43:04
 */
public class BaseController extends Controller {
	public static final Logger log=LoggerFactory.getLogger(BaseController.class);
	/**
	 * 检查用户是否登录用于控制
	 *
	 * @Title: before 
	 * @throws HtmlReqException
	 * @return: void
	 */
	@Before(unless={"BaseController.login", "BaseController.logout", 
			"BaseController.dologin", "BaseController.captcha", "BaseController.checkLogin"
			}, priority=1)
	public static void before() throws HtmlReqException{
		String ctxPath = Play.ctxPath;
		renderArgs.put("ctxPath", ctxPath==null?"":ctxPath);
		SystemOperator oper = getLoginUser();
		if(oper==null){
//			if("html".equals(request.format)){
//				login();
//				return;
//			}else if("txt".equals(request.format)){
//				renderRespondJson(ReturnCode.NOLOGIN,"用户未登录");
//				return;
//			}
			if("html".equals(request.format)&&"POST".equalsIgnoreCase(request.method)){
				renderRespondJson(ReturnCode.NOLOGIN,"用户未登录");
				return;
			}
			else{
				login();
				return;
			}
		}
		setLoginUser(oper);
		if(oper!=null){
			Result result = (Result) Cache.get(oper.getOperatorid()+"_"+session.getId());
			Cache.set(oper.getOperatorid()+"_"+session.getId(), result, "30mn");
		}
	}
	 /**
	 * 登录页面
	 *
	 * @Title: login 
	 * @return: void
	 */
    public static void login() {
    	String ctxPath = Play.ctxPath;
		renderArgs.put("ctxPath", ctxPath==null?"":ctxPath);
		String codeId = Codec.UUID();
		renderArgs.put("codeId", codeId);
        render();
    }
    /**
     * 登录
     *
     * @Title: dologin 
     * @param oper
     * @return: void
     */
    public static void dologin(String operatorid,String password,String codeId,String verifyCode){
    	if(StringUtils.isEmpty(operatorid)){
    		renderRespondJson(ReturnCode.ErrorCode,"用户名不能为空");
    	}
    	if(StringUtils.isEmpty(password)){
    		renderRespondJson(ReturnCode.ErrorCode,"密码不能为空");
    	}
    	SystemOperator SystemOperator=OperatorService.getById(operatorid);
    	if(SystemOperator==null){
    		renderRespondJson(ReturnCode.ErrorCode,"用户不存在");
    	}
    	if(new BigDecimal(2).equals(SystemOperator.getStatus())){
    		renderRespondJson(ReturnCode.ErrorCode,"用户被停用");
    	}
    	if(!validate(SystemOperator.getPassword(),SystemOperator.getSalt(),password)){
    		renderRespondJson(ReturnCode.ErrorCode,"密码错误");
    	}
    	BaseController.setLoginUser(SystemOperator);
    	renderRespondJson(ReturnCode.SuccessCode,SystemOperator.getOperatorname());
    }
    /**
	 * 图形验证码
	 * @param codeId 
	 */
	public static void captcha(String codeId) {
		response.setContentTypeIfNotSet("image/png");
	    Images.Captcha captcha = Images.captcha();
	    String code = captcha.getText("#49B07F",4);
	    Cache.set(codeId, code, "30mn");
	    renderBinary(captcha);
	}
    /**
     * 验证密码是否正确
     *
     * @Title: validate 
     * @param SystemOperatorVo DB中数据对象
     * @param password 用户密码
     * @return
     * @return: boolean
     */
	protected static boolean validate(String oldpass,String salt, String password) {
		// TODO Auto-generated method stub
		String pass=Codec.hexMD5(password+salt);
		return pass.equals(oldpass);
	}
	/**
	 * 登出
	 */
	public static void logout(){
		releaseSession();
		login();
	}
	/**
	 * 验证 密码是否正确
	 *
	 * @Title: checkPass 
	 * @param value 原始密码
	 * @return: void
	 */
	public static void checkPass(String value){
		SystemOperator oper=getLoginUser();
		if(StringUtils.isEmpty(value)){
			renderRespondJson(ReturnCode.ErrorCode,"原始密码为空");
		}
		SystemOperator oldoper=OperatorService.getById(oper.getOperatorid());
		if(!validate(oldoper.getPassword(),oldoper.getSalt(),value)){
			renderRespondJson(ReturnCode.ErrorCode,"密码不正确");
		}
		else{
			renderRespondJson(ReturnCode.SuccessCode,"验证通过");
		}
	}
	/**
	 * 更新密码
	 *
	 * @Title: updatePass 
	 * @param newpass
	 * @return: void
	 */
	public static void updatePass(String password,String confimpassword,String oldPassword){
		response.contentType="text/html;charset=utf-8";
		SystemOperator oper=getLoginUser();
		if(StringUtils.isEmpty(password)){
			renderRespondJson(ReturnCode.ErrorCode,"新密码不能为空");
		}
		if(password.length()<4){
			renderRespondJson(ReturnCode.ErrorCode,"密码长度不可低于4位");
		}
		if(password.length()>50){
			renderRespondJson(ReturnCode.ErrorCode,"密码长度不可高于50位");
		}
		if(!password.equals(confimpassword)){
			renderRespondJson(ReturnCode.ErrorCode,"两次录入密码输入不一致");
		}
		SystemOperator oldOper=OperatorService.getById(oper.getOperatorid());
		if(!validate(oldOper.getPassword(),oldOper.getSalt(),oldPassword)){
			renderRespondJson(ReturnCode.ErrorCode,"密码验证失败");
		}
		password=Codec.hexMD5(password+oldOper.getSalt());
		String ip=request.remoteAddress;
		boolean isok=OperatorService.updatePass(oldOper.getOperatorid(),password,oper,ip);
		if(isok){
			renderRespondJson(ReturnCode.SuccessCode,"修改成功");
		}
		else{
			renderRespondJson(ReturnCode.ErrorCode,"修改失败");
		}
	}
	/**
	 * 释放session资源
	 */
	private static void releaseSession(){
		SystemOperator oper = getLoginUser();
		if(oper!=null){
			Cache.safeDelete(BizConstants.SESSION_PREFIX + session.getId());
			Cache.safeDelete(oper.getOperatorid() + "_" + session.getId());
			Cache.safeDelete(oper.getOperatorid()+"_menu");
		}
		session.clear();
	}
	/**
	 * 检测登录状态
	 */
	public static void checkLogin(){
		SystemOperator oper = getLoginUser();
		if(oper==null){
			renderRespondJson(ReturnCode.NOLOGIN,"用户未登录");
		}else{
			renderRespondJson(ReturnCode.SuccessCode,"用户已登录");
		}
	}
	
	/**
	 * 返回数据
	 *
	 * @Title: renderFailedJson 
	 * @param code 状态代码
	 * @param msg 状态值
	 * @return: void
	 */
	protected static void renderRespondJson(int code, String msg) {
		renderJSON(JSON.toJSONString(new ResultVo(code, msg)));
	}
	/**
	 * 对返回数据进行包装，格式为：{"code":输入的code,"msg":""}
	 */
	protected static void renderRespondJson(int code) {
		renderJSON(JSON.toJSONString(new ResultVo(code)));
	}
	/**
	 * 得到当前用户登录信息
	 *
	 * @Title: getLoginUser 
	 * @return
	 * @return: User
	 */
	protected static SystemOperator getLoginUser(){
		SystemOperator oper = Cache.get(BizConstants.SESSION_PREFIX + session.getId(), SystemOperator.class);
		return oper;
	}
	/**
	 * 设置当前登录的用户
	 * @param user
	 */
	protected static void setLoginUser(SystemOperator oper){
		Cache.set(BizConstants.SESSION_PREFIX + session.getId(), oper, "30mn");
	}
	/**
	 * 
	 * 处理非法请求：未认证、会话过期等
	 * 
	 * @param failedReturnCode 针对Ajax请求返回的错误码
	 * @since v0.1
	 */
    protected static void handleIllegalRequest(int failedReturnCode) {

		// 针对Ajax请求返回特定格式的消息
		if (request.isAjax()) {
			renderRespondJson(failedReturnCode);
		}
		// 转向登录页
		redirect("/login");
	}
    /**
	 * 拦截json请求异常
	 * @param throwable
	 */
	@Catch(value=JSONReqException.class)
	public static void handleJSONReqException(Throwable throwable){
		//Logger.error(throwable.getMessage());
		renderRespondJson(ReturnCode.ErrorCode,"程序发生异常");
	}
	
	/**
	 * 拦截html请求异常
	 * @param throwable 
	 */
	@Catch(value=HtmlReqException.class)
	public static void hanlderHtmlReqException(Throwable throwable){
		notFound();
	}
	/**
	 * 检查是否拥有权限
	 *
	 * @Title: checkAuthority 
	 * @return: void
	 */
	public static boolean checkAuthority(String id){
		SystemOperator oper=getLoginUser();
		boolean isExist=AuthorityService.isExist(id,oper.getOperatorid());
		return isExist;
	}
	/**
	 * 
	 * 防御CSRF攻击（所有的POST请求必须带上token）
	 *
	 * @since  0.1
	 * @author youblade
	 * @created 2014年8月5日 下午1:41:51
	 */
    @Before(priority = 0)
    public static void checkAuthenticityToken() {
        if ("POST".equalsIgnoreCase(request.method)) {
            checkAuthenticity();
        }
    }
	public static void Notf(){
		render("errors/404.html");
	}
	
	protected static void exportWordOrZip(String html,String downloadFileName){
		try{
			FileInputStream inputStream = HtmlToDoc.writeToWordFile(html);
			downloadFileName = downloadFileName + ".doc";
			
			renderBinary(inputStream, downloadFileName);
			
		}catch(Exception e){
			log.error("导出Word文档失败!",e);
		}
		
	}
}
